package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
)

// GitCloneOverSSH 通过SSH连接到远程主机并执行git clone
func GitCloneOverSSH(sshConfig *SSHConfig, repoURL, targetDir string) error {
	// 创建SSH客户端配置
	config := &ssh.ClientConfig{
		User: sshConfig.Username,
		Auth: []ssh.AuthMethod{
			publicKeyAuth(sshConfig.PrivateKeyPath),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 生产环境应使用更安全的方式
	}

	// 连接到SSH服务器
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", sshConfig.Host, sshConfig.Port), config)
	if err != nil {
		return fmt.Errorf("failed to dial SSH server: %v", err)
	}
	defer func(client *ssh.Client) {
		err := client.Close()
		if err != nil {

		}
	}(client)

	// 创建新的SSH会话
	session, err := client.NewSession()
	if err != nil {
		return fmt.Errorf("failed to create SSH session: %v", err)
	}
	defer func(session *ssh.Session) {
		err := session.Close()
		if err != nil {

		}
	}(session)

	// 设置标准输出和错误输出
	session.Stdout = os.Stdout
	session.Stderr = os.Stderr

	// 确保目标目录存在
	cmd := fmt.Sprintf("mkdir -p %s && cd %s && git clone %s", targetDir, targetDir, repoURL)

	// 执行命令
	if err := session.Run(cmd); err != nil {
		return fmt.Errorf("failed to run git clone command: %v", err)
	}

	return nil
}

// SSHConfig SSH连接配置
type SSHConfig struct {
	Host           string
	Port           int
	Username       string
	PrivateKeyPath string
}

// publicKeyAuth 使用私钥文件创建SSH认证方法
func publicKeyAuth(privateKeyPath string) ssh.AuthMethod {
	key, err := ioutil.ReadFile(privateKeyPath)
	if err != nil {
		log.Fatalf("unable to read private key: %v", err)
	}

	signer, err := ssh.ParsePrivateKey(key)
	if err != nil {
		log.Fatalf("unable to parse private key: %v", err)
	}

	return ssh.PublicKeys(signer)
}

func main() {
	// 示例用法
	config := &SSHConfig{
		Host:           "example.com",
		Port:           22,
		Username:       "username",
		PrivateKeyPath: filepath.Join(os.Getenv("HOME"), ".ssh", "id_rsa"),
	}

	repoURL := "git@github.com:example/repo.git"
	targetDir := "/path/to/target/directory"

	err := GitCloneOverSSH(config, repoURL, targetDir)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	fmt.Println("Git clone completed successfully")
}
